﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace VideoLibrary
{
    public class Media
    {
        [DllImport("winmm.dll")]
        public static extern int mciSendString(string m_strCmd, StringBuilder m_strReceive, int m_v1, int m_v2);
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public static extern int GetShortPathName(string lpszLongPath, StringBuilder shortFile, int cchBuffer);
        [DllImport("winmm.dll", EntryPoint = "mciGetDeviceID", CharSet = CharSet.Auto)]
        private static extern int mciGetDeviceID(string lpstrName);
        public Media()
        {

        }
        public Media(string file)
        {
            //打开  file 这个路径的歌曲，type mpegvideo是文件类型，alias 是将文件别名为media 
            CloseAllMedia();
            mciSendString("open \"" + file + "\" type mpegvideo alias media", null, 0, 0);
        }

        /// <summary>
        /// 声道
        /// </summary>
        public enum AudioSource : byte
        {
            left = 0,//左
            right = 1,//右
            average = 2,//平均
            stereo = 3//立体声
        }

        /// <summary>
        /// 根据文件名，确定设备
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public string GetDriverID(string fileName)
        {
            string result = "";
            fileName = fileName.ToUpper().Trim().Substring(fileName.Length - 3);
            switch (fileName)
            {
                case "MID":
                case "RMI":
                case "IDI":
                    result = "Sequencer";
                    break;
                case "WAV":
                    result = "Waveaudio";
                    break;
                case "ASX":
                case "IVF":
                case "LSF":
                case "LSX":
                case "P2V":
                case "WAX":
                case "WVX":
                case "WMX":
                case "WMP":
                case ".WM":
                    result = "MPEGVideo2";
                    break;
                case ".RM":
                case "RAM":
                case ".RA":
                case "MVB":
                    result = "RealPlay";
                    break;
                default:
                    result = "MPEGVideo";
                    break;
            }
            return result;
        }

        /// <summary>
        /// 播放Media
        /// </summary>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        public bool PlayMedia(double? start = null, double? end = null)
        {
            StopMedia();
            StringBuilder sbr = new StringBuilder("play media notify");
            if (start != null)
            {
                sbr.Append(" from " + start);
            }
            if (end != null)
            {
                sbr.Append(" to " + end);
            }
            return mciSendString(sbr.ToString(), null, 0, 0) == 0;
        }

        /// <summary>
        /// 将Media定位到某个位置
        /// </summary>
        /// <returns></returns>
        public bool MediaSeekToPostion(double milliseconds)
        {
            return mciSendString("seek media to " + milliseconds, null, 0, 0) == 0;
        }

        /// <summary>
        /// 将Media定位到开头位置
        /// </summary>
        /// <returns></returns>
        public bool MediaSeekToStart()
        {
            return mciSendString("seek media to start", null, 0, 0) == 0;
        }

        /// <summary>
        /// 将Media定位到最后位置
        /// </summary>
        /// <returns></returns>
        public bool MediaSeekToEnd()
        {
            return mciSendString("seek media to start", null, 0, 0) == 0;
        }

        /// <summary>
        /// 暂停Media
        /// </summary>
        /// <returns></returns>
        public bool PauseMedia()
        {
            return mciSendString("pause media", null, 0, 0) == 0;
        }

        /// <summary>
        /// 继续Media
        /// </summary>
        /// <returns></returns>
        public bool ResumeMedia()
        {
            return mciSendString("resume media", null, 0, 0) == 0;
        }

        /// <summary>
        /// 循环播放Media
        /// </summary>
        /// <returns></returns>
        public bool RepeatPlayMedia()
        {
            return mciSendString("play movie repeat", null, 0, 0) == 0;
        }

        /// <summary>
        /// 停止Media
        /// </summary>
        /// <returns></returns>
        public bool StopMedia()
        {
            return mciSendString("stop media", null, 0, 0) == 0;
        }

        /// <summary>
        /// 前进Media
        /// </summary>
        /// <returns></returns>
        public bool ForwardMedia()
        {
            return mciSendString("step media", null, 0, 0) == 0;
        }

        /// <summary>
        /// 后退Media
        /// </summary>
        /// <returns></returns>
        public bool ReverseMedia()
        {
            return mciSendString("step media reverse", null, 0, 0) == 0;
        }

        /// <summary>
        /// 前进或后退N個位置Media，其中N＜0即表示后退
        /// </summary>
        /// <returns></returns>
        public bool ReverseMedia(int num)
        {
            return mciSendString("step media by " + num, null, 0, 0) == 0;
        }

        /// <summary>
        /// 关闭Media
        /// </summary>
        /// <returns></returns>
        public bool CloseMedia()
        {
            return mciSendString("close media", null, 0, 0) == 0;
        }

        /// <summary>
        /// 关闭AllMedia
        /// </summary>
        /// <returns></returns>
        public bool CloseAllMedia()
        {
            return mciSendString("close all", null, 0, 0) == 0;
        }

        /// <summary>
        /// 获取Media当前模式
        /// </summary>
        /// <returns></returns>
        public string GetMediaMode()
        {
            StringBuilder sb = new StringBuilder();
            if (mciSendString("status media mode", sb, 100, 0) == 0 && !string.IsNullOrEmpty(sb.ToString()))
            {
                return sb.ToString();
            }
            return "not ready";
        }

        /// <summary>
        /// 获取声音大小
        /// </summary>
        /// <returns></returns>
        public string GetMediaVolume()
        {
            StringBuilder sb = new StringBuilder();
            if (mciSendString("status media volume", sb, 100, 0) == 0 && !string.IsNullOrEmpty(sb.ToString()))
            {
                return sb.ToString();
            }
            return "0";
        }

        /// <summary>
        /// 设置声音大小
        /// </summary>
        /// <param name="volume"></param>
        /// <returns></returns>
        public bool SetMediaVolume(int volume)
        {
            return mciSendString("setaudio media volume to " + volume, null, 0, 0) == 0;
        }

        /// <summary>
        /// 获取亮度大小，用于播放视频
        /// </summary>
        /// <returns></returns>
        public string GetMediaBrightness()
        {
            StringBuilder sb = new StringBuilder();
            if (mciSendString("status media brightness", sb, 100, 0) == 0 && !string.IsNullOrEmpty(sb.ToString()))
            {
                return sb.ToString();
            }
            return "0";
        }

        /// <summary>
        /// 设置亮度大小，用于播放视频
        /// </summary>
        /// <param name="volume"></param>
        /// <returns></returns>
        public bool SetMediaBrightness(int brightness)
        {
            return mciSendString("setvideo media brightness to " + brightness, null, 0, 0) == 0;
        }

        /// <summary>
        /// 设置静音 True为取消静音，FALSE为静音
        /// </summary>
        /// <param name="isOpen"></param>
        /// <returns></returns>
        public bool SetAudioOnOff(bool isClose)
        {
            string nowMusic = isClose ? "off" : "on";
            return mciSendString("setaudio media " + nowMusic, null, 0, 0) == 0;
        }

        /// <summary>
        /// 设置声道
        /// </summary>
        /// <param name="audioSource"></param>
        /// <returns></returns>
        public bool SetAudioSource(AudioSource audioSource)
        {
            string strSource = "";
            switch (audioSource)
            {
                case AudioSource.left:
                    strSource = "left";
                    break;
                case AudioSource.right:
                    strSource = "right";
                    break;
                case AudioSource.average:
                    strSource = "average";
                    break;
                case AudioSource.stereo:
                    strSource = "stereo";
                    break;
                default:
                    break;
            }
            return mciSendString("setaudio media source to " + strSource, null, 0, 0) == 0;
        }

        /// <summary>
        /// 在指定控件上播放视频
        /// </summary>
        /// <param name="volume"></param>
        /// <returns></returns>
        public bool PlayMedia(string fileName, IntPtr hWnd)
        {
            StringBuilder sbr = new StringBuilder("open ");
            sbr.Append(fileName);
            sbr.Append(" alias MyAVI parent ");
            sbr.Append(hWnd);
            sbr.Append(" style child");
            mciSendString(sbr.ToString(), null, 0, 0);

            SetPutMedia(0, 0, 200, 200);
            return mciSendString("play MyAVI", null, 0, 0) == 0;
        }

        /// <summary>
        /// 获取视频的尺寸
        /// </summary>
        /// <returns></returns>
        public string GetMediaDestination()
        {
            StringBuilder sbr = new StringBuilder();
            if (mciSendString("where MyAVI destination", sbr, 0, 0) == 0 && string.IsNullOrEmpty(sbr.ToString()))
            {
                return sbr.ToString();
            }
            return "";
        }

        /// <summary>
        /// 决定显示源和显示目的窗口的区域
        /// </summary>
        /// <param name="volume"></param>
        /// <returns></returns>
        public bool SetPutMedia(int x, int y, int width, int height)
        {
            StringBuilder sbr = new StringBuilder("put MyAVI window at ");
            sbr.Append(x + " ");
            sbr.Append(y + " ");
            sbr.Append(width + " ");
            sbr.Append(height);
            return mciSendString(sbr.ToString(), null, 0, 0) == 0;
        }

        /// <summary>
        /// 开始录音
        /// </summary>
        /// <returns></returns>
        public bool StartRecordSound()
        {
            //设为8位
            mciSendString("set wave bitpersample 8", null, 0, 0);
            //设为11025Hz
            mciSendString("set wave samplespersec 11025", null, 0, 0);
            //设为立体声
            mciSendString("set wave channels 2", null, 0, 0);
            //实现PCM格式
            mciSendString("set wave format tag pcm", null, 0, 0);
            CloseAllMedia();
            mciSendString("open new type WAVEAudio alias media", null, 0, 0);
            return mciSendString("record media", null, 0, 0) == 0;
        }

        /// <summary>
        /// 结束录音，并保存文件
        /// </summary>
        /// <returns></returns>
        public bool StopRecordSound(string path)
        {
            mciSendString("stop media", null, 0, 0);
            mciSendString("save media " + path, null, 0, 0);
            return mciSendString("close media", null, 0, 0) == 0;
        }

        /// <summary>
        /// 获取当前Media的长度，并用hh:mm:ss:ms格式返回
        /// </summary>
        /// <returns></returns>
        public string GetMusicLengthString()
        {
            StringBuilder sb = new StringBuilder();
            if (mciSendString("Status media length", sb, 1000, 0) == 0 && !string.IsNullOrEmpty(sb.ToString()))
            {
                return GetTimeStringByMilliseconds(int.Parse(sb.ToString()));
            }
            return "00:00:00:00";
        }

        /// <summary>
        /// 获取当前Media的位置，并用hh:mm:ss:ms格式返回
        /// </summary>
        /// <returns></returns>
        public string GetMusicPosString()
        {
            StringBuilder sb = new StringBuilder();
            if (mciSendString("Status media position", sb, 1000, 0) == 0 && !string.IsNullOrEmpty(sb.ToString()))
            {
                return GetTimeStringByMilliseconds(int.Parse(sb.ToString()));
            }
            return "00:00:00:00";
        }

        /// <summary>
        /// 根据格式hh:mm:ss:ms的字符串返回TimeSpan
        /// </summary>
        /// <param name="dateTime"></param>
        /// <returns></returns>
        public TimeSpan GetTimeSpan(string dateTime)
        {
            string[] startTimeArr = dateTime.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
            int days = 0, hours, minutes, seconds, mseconds;
            int.TryParse(startTimeArr[0], out hours);
            int.TryParse(startTimeArr[1], out minutes);
            int.TryParse(startTimeArr[2], out seconds);
            int.TryParse(startTimeArr[3], out mseconds);
            return new TimeSpan(days, hours, minutes, seconds, mseconds);
        }

        /// <summary>
        /// 打开光驱
        /// </summary>
        /// <returns></returns>
        public bool OpenCdaudio()
        {
            return mciSendString("set cdaudio door open", null, 0, 0) == 0;
        }

        /// <summary>
        /// 关闭光驱
        /// </summary>
        /// <returns></returns>
        public bool CloseCdaudio()
        {
            return mciSendString("set cdaudio door close", null, 0, 0) == 0;
        }

        /// <summary>
        /// 根据毫秒获取hh:mm:ss:ms格式的字符串
        /// </summary>
        /// <param name="milliseconds"></param>
        /// <returns></returns>
        public string GetTimeStringByMilliseconds(int milliseconds)
        {
            int hour = milliseconds / (1000 * 60 * 24);
            //计算分钟,用毫秒总数减去小时乘以(1000*60*24)后,除以(1000*60),再去掉小数点
            int min = (milliseconds - hour * (1000 * 60 * 24)) / (1000 * 60);
            //同上
            int sec = (milliseconds - hour * (1000 * 60 * 24) - min * (1000 * 60)) / 1000;
            int msec = milliseconds - hour * (1000 * 60 * 24) - min * (1000 * 60) - sec * 1000;
            return string.Format("{0:D2}:{1:D2}:{2:D2}:{3:D2}", hour, min, sec, msec);
        }

        /// <summary>
        /// 根据秒获取hh:mm:ss格式的字符串
        /// </summary>
        /// <param name="mtime"></param>
        /// <returns></returns>
        public string GetTimeStringBySeconds(int seconds)
        {
            int hour = seconds / (60 * 24);
            //计算分钟,用秒总数减去小时乘以(60*24)后,除以(60),再去掉小数点
            int min = (seconds - hour * (60 * 24)) / (60);
            //同上
            int sec = seconds - hour * (60 * 24) - min * (60);
            return string.Format("{0:D2}:{1:D2}:{2:D2}", hour, min, sec);
        }
    }
}
